﻿
using CatEars.Core.Collections;

namespace System.IO
{
    /// <summary>
    /// 流操作扩展
    /// </summary>
    public static class ExStream
    {
        static readonly int DefaultBufferSize = 8192;

        #region ToMemoryStream
        /// <summary>
        /// 将一个流拷贝到内存流
        /// </summary>
        /// <param name="stream">流【NotNull】</param>
        /// <returns>MemoryStream</returns>
        public static MemoryStream ToMemoryStream(this Stream stream)
        {
            MemoryStream ms = null;
            try
            {
                if (!stream.CanRead)
                {
                    throw new NotSupportedException();
                }
                try
                {
                    if (stream.CanSeek)
                    {
                        ms = new MemoryStream((int)stream.Length);
                    }
                    else
                    {
                        ms = new MemoryStream();
                    }
                }
                catch
                {
                    ms = new MemoryStream();
                }
                CopyToStream(stream, ms);
                ms.Seek(0, SeekOrigin.Begin);
            }
            catch
            {
                if (ms != null)
                {
                    ms.Dispose();
                }
                throw;
            }
            return ms;
        }
        /// <summary>
        /// 将一个流拷贝到内存流
        /// </summary>
        /// <param name="stream">流【NotNull】</param>
        /// <returns>MemoryStream</returns>
        public static MemoryStream ToMemoryStream(this BinaryReader stream)
        {
            MemoryStream ms = null;
            try
            {
                ms = new MemoryStream();
                CopyToStream(stream, ms);
                ms.Seek(0, SeekOrigin.Begin);
            }
            catch
            {
                if (ms != null)
                {
                    ms.Dispose();
                }
                throw;
            }
            return ms;
        }
        /// <summary>
        /// 将一个byte[]拷贝到内存流
        /// (直接用MemoryStream的构造函数得到的是只读的，这个是可写的)
        /// </summary>
        /// <param name="buffer">流【NotNull】</param>
        /// <returns>MemoryStream</returns>
        public static MemoryStream ToMemoryStream(this byte[] buffer)
        {
            MemoryStream ms = null;
            try
            {
                ms = new MemoryStream(buffer.Length);
                ms.Write(buffer, 0, buffer.Length);
                ms.Seek(0, SeekOrigin.Begin);
            }
            catch
            {
                if (ms != null)
                {
                    ms.Dispose();
                }
                throw;
            }
            return ms;
        }
        #endregion

        #region CopyToStream
        /// <summary>
        /// 拷贝流中的数据（to注意将指针移到开头）
        /// </summary>
        /// <param name="from">【NotNull】</param>
        /// <param name="to">直接写入 使用时注意to的指针位置【NotNull】</param>
        /// <param name="intBufferSize"></param>
        /// <returns>复制的字节数</returns>
        public static int CopyToStream(this Stream from, Stream to, int intBufferSize = 0)
        {
            if (!from.CanRead)
            {
                throw new NotSupportedException();
            }
            intBufferSize = Math.Max(DefaultBufferSize, intBufferSize);
            byte[] buffer = new byte[intBufferSize];
            int intCount = 0;
            int intRead;
            do
            {
                intRead = from.Read(buffer, 0, intBufferSize);
                if (intRead > 0)
                {
                    intCount += intRead;
                    to.Write(buffer, 0, intRead);
                }
            }
            while (intRead > 0);
            return intCount;
        }

        /// <summary>
        /// 拷贝流中的数据
        /// </summary>
        /// <param name="from">【NotNull】</param>
        /// <param name="to">直接写入 使用时注意to的指针位置【NotNull】</param>
        /// <param name="intBufferSize"></param>
        /// <returns>复制的字节数</returns>
        public static int CopyToStream(this BinaryReader from, Stream to, int intBufferSize = 0)
        {
            intBufferSize = Math.Max(8192, intBufferSize);
            byte[] buffer = new byte[intBufferSize];
            int intCount = 0;
            int intRead;
            do
            {
                intRead = from.Read(buffer, 0, intBufferSize);
                if (intRead > 0)
                {
                    intCount += intRead;
                    to.Write(buffer, 0, intRead);
                }
            }
            while (intRead > 0);
            return intCount;
        }
        #endregion

        #region 流读取

        /// <summary>
        /// 从流中读取指定字节
        /// </summary>
        /// <param name="stream">【NotNull】</param>
        /// <param name="intReadLength"></param>
        /// <returns></returns>
        public static byte[] ReadBytes(this Stream stream, int intReadLength)
        {
            byte[] buffer = new byte[intReadLength];
            int intRead = stream.Read(buffer, 0, intReadLength);
            if (intRead == intReadLength) return buffer;
            if (intRead == 0) return EmptyArray.ByteArray;
            byte[] buffer2 = new byte[intRead];
            Array.Copy(buffer, buffer2, intRead);
            return buffer2;
        }

        /// <summary>
        /// 从流中读取所有字节
        /// </summary>
        /// <param name="stream">【NotNull】</param>
        /// <returns></returns>
        public static byte[] ReadAllBytes(this Stream stream)
        {
            using (var ms = ToMemoryStream(stream))
            {
                return ms.ToArray();
            }
        }

        #endregion
    }
}
